1. 程式人生 > >ESP8266 SDK學習筆記(四):Makefile分析

ESP8266 SDK學習筆記(四):Makefile分析

主要內容

本章我們來分析SDK中的Makefile,同時學習如何建立自己的原始碼資料夾。

預備知識

一份程式碼工程編譯成二進位制可執行檔案,需要經過四個步驟:預處理、編譯、彙編和連結。

進行編譯需要有編譯器,Linux環境下使用的是gcc,而對應的,ESP8266使用的編譯器是xtensa-lx106-elf-gcc。在後面分析Makefile中,我們就會看到該編譯器。

下面是其他一些工具的含義:

  • ar:用於建立或修改備存檔案,或是從備存檔案中抽取檔案
  • nm:用來列出目標檔案的符號清單
  • objcopy:將目標檔案的一部分或者全部內容拷貝到另外一個目標檔案中,或者實現目標檔案的格式轉換
  • objdump:檢視目標檔案或者可執行的目標檔案的構成

Makefile分析

首先我們來看看ESP8266 SDK的目錄結構以及Makefile:

LicenseMakefile # 主目錄下的Makefile
├─app/
│   │  Makefile
│   ├─ driver
│   └─ user
│       └─ Makefile
├─bin
├─documents
├─driver_lib  
├─examples
├─lib
├─include    
├─ld
└─tools

由此可見,我們至少要分析三個Makefile:

  • 主目錄下的Makefile
  • app目錄下的Makefile
  • app/user/的Makefile

主目錄下的Makefile

下面我們來hack一下主目錄下的Makefile,詳細解釋請看註釋:

#  copyright (c) 2010 Espressif System
#
ifndef PDIR

endif

############################################
# 編譯工具配置
# ESP8266 主要使用的編譯器是 xtensa-lx106-elf-gcc

ifeq ($(COMPILE), gcc)
    AR = xtensa-lx106-elf-ar
    CC
= xtensa-lx106-elf-gcc NM = xtensa-lx106-elf-nm CPP = xtensa-lx106-elf-cpp OBJCOPY = xtensa-lx106-elf-objcopy OBJDUMP = xtensa-lx106-elf-objdump else AR = xt-ar CC = xt-xcc NM = xt-nm CPP = xt-cpp OBJCOPY = xt-objcopy OBJDUMP = xt-objdump endif ############################################ # 引數預設配置 # =none - 不使用boot # =old - 使用老版本的boot_v1.1+ # =new - 使用新版本的boot_v1.2+ BOOT?=none # =0 - 不使用遠端升級FOTA # =1 - 使用FOTA,生成user1.<flash_map>.<BOOT>.bin # =2 - 使用FOTA,生成user2.<flash_map>.<BOOT>.bin APP?=0 # SPI速率和模式,一般不用改動 SPI_SPEED?=40 SPI_MODE?=QIO # SPI_SIZE_MAP flash對映方式 # 4MB Flash使用 SPI_SIZE_MAP?=4 SPI_SIZE_MAP?=4 ############################################ ifeq ($(BOOT), new) boot = new else ifeq ($(BOOT), old) boot = old else boot = none endif endif ifeq ($(APP), 1) app = 1 else ifeq ($(APP), 2) app = 2 else app = 0 endif endif ifeq ($(SPI_SPEED), 26.7) freqdiv = 1 else ifeq ($(SPI_SPEED), 20) freqdiv = 2 else ifeq ($(SPI_SPEED), 80) freqdiv = 15 else freqdiv = 0 endif endif endif ifeq ($(SPI_MODE), QOUT) mode = 1 else ifeq ($(SPI_MODE), DIO) mode = 2 else ifeq ($(SPI_MODE), DOUT) mode = 3 else mode = 0 endif endif endif addr = 0x01000 ifeq ($(SPI_SIZE_MAP), 1) size_map = 1 flash = 256 else ifeq ($(SPI_SIZE_MAP), 2) size_map = 2 flash = 1024 ifeq ($(app), 2) addr = 0x81000 endif else ifeq ($(SPI_SIZE_MAP), 3) size_map = 3 flash = 2048 ifeq ($(app), 2) addr = 0x81000 endif else ifeq ($(SPI_SIZE_MAP), 4) size_map = 4 flash = 4096 ifeq ($(app), 2) addr = 0x81000 endif else ifeq ($(SPI_SIZE_MAP), 5) size_map = 5 flash = 2048 ifeq ($(app), 2) addr = 0x101000 endif else ifeq ($(SPI_SIZE_MAP), 6) size_map = 6 flash = 4096 ifeq ($(app), 2) addr = 0x101000 endif else size_map = 0 flash = 512 ifeq ($(app), 2) addr = 0x41000 endif endif endif endif endif endif endif ############################################ # 選擇連結工具 # 這裡選擇了主目錄下的 ld/eagle.app.v6.ld LD_FILE = $(LDDIR)/eagle.app.v6.ld # 如果boot!=none,才進入這裡 ifneq ($(boot), none) ifneq ($(app),0) ifeq ($(size_map), 6) LD_FILE = $(LDDIR)/eagle.app.v6.$(boot).2048.ld else ifeq ($(size_map), 5) LD_FILE = $(LDDIR)/eagle.app.v6.$(boot).2048.ld else ifeq ($(size_map), 4) LD_FILE = $(LDDIR)/eagle.app.v6.$(boot).1024.app$(app).ld else ifeq ($(size_map), 3) LD_FILE = $(LDDIR)/eagle.app.v6.$(boot).1024.app$(app).ld else ifeq ($(size_map), 2) LD_FILE = $(LDDIR)/eagle.app.v6.$(boot).1024.app$(app).ld else ifeq ($(size_map), 0) LD_FILE = $(LDDIR)/eagle.app.v6.$(boot).512.app$(app).ld endif endif endif endif endif endif BIN_NAME = user$(app).$(flash).$(boot).$(size_map) endif else app = 0 endif ############################################ CSRCS ?= $(wildcard *.c) ASRCs ?= $(wildcard *.s) ASRCS ?= $(wildcard *.S) SUBDIRS ?= $(patsubst %/,%,$(dir $(wildcard */Makefile))) ODIR := .output OBJODIR := $(ODIR)/$(TARGET)/$(FLAVOR)/obj # 設定 OBJS 變數 OBJS := $(CSRCS:%.c=$(OBJODIR)/%.o) \ $(ASRCs:%.s=$(OBJODIR)/%.o) \ $(ASRCS:%.S=$(OBJODIR)/%.o) # 設定 DEPS 變數 DEPS := $(CSRCS:%.c=$(OBJODIR)/%.d) \ $(ASRCs:%.s=$(OBJODIR)/%.d) \ $(ASRCS:%.S=$(OBJODIR)/%.d) # 設定 LIBODIR 庫資料夾 LIBODIR := $(ODIR)/$(TARGET)/$(FLAVOR)/lib OLIBS := $(GEN_LIBS:%=$(LIBODIR)/%) IMAGEODIR := $(ODIR)/$(TARGET)/$(FLAVOR)/image OIMAGES := $(GEN_IMAGES:%=$(IMAGEODIR)/%) # 設定 BINODIR 二進位制資料夾 BINODIR := $(ODIR)/$(TARGET)/$(FLAVOR)/bin OBINS := $(GEN_BINS:%=$(BINODIR)/%) ############################################################# CCFLAGS += \ -g \ -Wpointer-arith \ -Wundef \ -Werror \ -Wl,-EL \ -fno-inline-functions \ -nostdlib \ -mlongcalls \ -mtext-section-literals \ -ffunction-sections \ -fdata-sections \ -fno-builtin-printf # -Wall CFLAGS = $(CCFLAGS) $(DEFINES) $(EXTRA_CCFLAGS) $(INCLUDES) DFLAGS = $(CCFLAGS) $(DDEFINES) $(EXTRA_CCFLAGS) $(INCLUDES) ############################################################# # Functions # define ShortcutRule $(1): .subdirs $(2)/$(1) endef define MakeLibrary DEP_LIBS_$(1) = $$(foreach lib,$$(filter %.a,$$(COMPONENTS_$(1))),$$(dir $$(lib))$$(LIBODIR)/$$(notdir $$(lib))) DEP_OBJS_$(1) = $$(foreach obj,$$(filter %.o,$$(COMPONENTS_$(1))),$$(dir $$(obj))$$(OBJODIR)/$$(notdir $$(obj))) $$(LIBODIR)/$(1).a: $$(OBJS) $$(DEP_OBJS_$(1)) $$(DEP_LIBS_$(1)) $$(DEPENDS_$(1)) @mkdir -p $$(LIBODIR) $$(if $$(filter %.a,$$?),mkdir -p $$(EXTRACT_DIR)_$(1)) $$(if $$(filter %.a,$$?),cd $$(EXTRACT_DIR)_$(1); $$(foreach lib,$$(filter %.a,$$?),$$(AR) xo $$(UP_EXTRACT_DIR)/$$(lib);)) $$(AR) ru $$@ $$(filter %.o,$$?) $$(if $$(filter %.a,$$?),$$(EXTRACT_DIR)_$(1)/*.o) $$(if $$(filter %.a,$$?),$$(RM) -r $$(EXTRACT_DIR)_$(1)) endef define MakeImage DEP_LIBS_$(1) = $$(foreach lib,$$(filter %.a,$$(COMPONENTS_$(1))),$$(dir $$(lib))$$(LIBODIR)/$$(notdir $$(lib))) DEP_OBJS_$(1) = $$(foreach obj,$$(filter %.o,$$(COMPONENTS_$(1))),$$(dir $$(obj))$$(OBJODIR)/$$(notdir $$(obj))) $$(IMAGEODIR)/$(1).out: $$(OBJS) $$(DEP_OBJS_$(1)) $$(DEP_LIBS_$(1)) $$(DEPENDS_$(1)) @mkdir -p $$(IMAGEODIR) $$(CC) $$(LDFLAGS) $$(if $$(LINKFLAGS_$(1)),$$(LINKFLAGS_$(1)),$$(LINKFLAGS_DEFAULT) $$(OBJS) $$(DEP_OBJS_$(1)) $$(DEP_LIBS_$(1))) -o $$@ endef $(BINODIR)/%.bin: $(IMAGEODIR)/%.out @mkdir -p $(BINODIR) ifeq ($(APP), 0) @$(RM) -r ../bin/eagle.S ../bin/eagle.dump @$(OBJDUMP) -x -s $< > ../bin/eagle.dump @$(OBJDUMP) -S $< > ../bin/eagle.S else mkdir -p ../bin/upgrade @$(RM) -r ../bin/upgrade/$(BIN_NAME).S ../bin/upgrade/$(BIN_NAME).dump @$(OBJDUMP) -x -s $< > ../bin/upgrade/$(BIN_NAME).dump @$(OBJDUMP) -S $< > ../bin/upgrade/$(BIN_NAME).S endif @$(OBJCOPY) --only-section .text -O binary $< eagle.app.v6.text.bin @$(OBJCOPY) --only-section .data -O binary $< eagle.app.v6.data.bin @$(OBJCOPY) --only-section .rodata -O binary $< eagle.app.v6.rodata.bin @$(OBJCOPY) --only-section .irom0.text -O binary $< eagle.app.v6.irom0text.bin @echo "" @echo "!!!" # 預設是 app==0 # 下面是輸出列印資訊 ifeq ($(app), 0) @python ../tools/gen_appbin.py $< 0 $(mode) $(freqdiv) $(size_map) $(app) @mv eagle.app.flash.bin ../bin/eagle.flash.bin @mv eagle.app.v6.irom0text.bin ../bin/eagle.irom0text.bin @rm eagle.app.v6.* @echo "No boot needed." @echo "Generate eagle.flash.bin and eagle.irom0text.bin successully in folder bin." @echo "eagle.flash.bin-------->0x00000" @echo "eagle.irom0text.bin---->0x10000" else ifneq ($(boot), new) @python ../tools/gen_appbin.py $< 1 $(mode) $(freqdiv) $(size_map) $(app) @echo "Support boot_v1.1 and +" else @python ../tools/gen_appbin.py $< 2 $(mode) $(freqdiv) $(size_map) $(app) ifeq ($(size_map), 6) @echo "Support boot_v1.4 and +" else ifeq ($(size_map), 5) @echo "Support boot_v1.4 and +" else @echo "Support boot_v1.2 and +" endif endif endif @mv eagle.app.flash.bin ../bin/upgrade/$(BIN_NAME).bin @rm eagle.app.v6.* @echo "Generate $(BIN_NAME).bin successully in folder bin/upgrade." @echo "boot.bin------------>0x00000" @echo "$(BIN_NAME).bin--->$(addr)" endif @echo "!!!" ############################################################# # Rules base # Should be done in top-level makefile only # ############################################ # make all執行的方法 all: .subdirs $(OBJS) $(OLIBS) $(OIMAGES) $(OBINS) $(SPECIAL_MKTARGETS) ############################################ # make clean執行的方法 clean: $(foreach d, $(SUBDIRS), $(MAKE) -C $(d) clean;) $(RM) -r $(ODIR)/$(TARGET)/$(FLAVOR) clobber: $(SPECIAL_CLOBBER) $(foreach d, $(SUBDIRS), $(MAKE) -C $(d) clobber;) $(RM) -r $(ODIR) .subdirs: @set -e; $(foreach d, $(SUBDIRS), $(MAKE) -C $(d);) #.subdirs: # $(foreach d, $(SUBDIRS), $(MAKE) -C $(d)) ifneq ($(MAKECMDGOALS),clean) ifneq ($(MAKECMDGOALS),clobber) ifdef DEPS sinclude $(DEPS) endif endif endif # “$<”表示所有的依賴目標集(所有.c字尾檔案),“[email protected]”表示目標集(所有.o字尾檔案) $(OBJODIR)/%.o: %.c @mkdir -p $(OBJODIR); $(CC) $(if $(findstring $<,$(DSRCS)),$(DFLAGS),$(CFLAGS)) $(COPTS_$(*F)) -o [email protected] -c $< $(OBJODIR)/%.d: %.c @mkdir -p $(OBJODIR); @echo DEPEND: $(CC) -M $(CFLAGS) $< @set -e; rm -f [email protected]; \ $(CC) -M $(CFLAGS) $< > [email protected].$$$$; \ sed 's,\($*\.o\)[ :]*,$(OBJODIR)/\1 [email protected] : ,g' < [email protected].$$$$ > [email protected]; \ rm -f [email protected].$$$$ $(OBJODIR)/%.o: %.s @mkdir -p $(OBJODIR); $(CC) $(CFLAGS) -o [email protected] -c $< $(OBJODIR)/%.d: %.s @mkdir -p $(OBJODIR); \ set -e; rm -f [email protected]; \ $(CC) -M $(CFLAGS) $< > [email protected].$$$$; \ sed 's,\($*\.o\)[ :]*,$(OBJODIR)/\1 [email protected] : ,g' < [email protected].$$$$ > [email protected]; \ rm -f [email protected].$$$$ $(OBJODIR)/%.o: %.S @mkdir -p $(OBJODIR); $(CC) $(CFLAGS) -D__ASSEMBLER__ -o [email protected] -c $< $(OBJODIR)/%.d: %.S @mkdir -p $(OBJODIR); \ set -e; rm -f [email protected]; \ $(CC) -M $(CFLAGS) $< > [email protected].$$$$; \ sed 's,\($*\.o\)[ :]*,$(OBJODIR)/\1 [email protected] : ,g' < [email protected].$$$$ > [email protected]; \ rm -f [email protected].$$$$ $(foreach lib,$(GEN_LIBS),$(eval $(call ShortcutRule,$(lib),$(LIBODIR)))) $(foreach image,$(GEN_IMAGES),$(eval $(call ShortcutRule,$(image),$(IMAGEODIR)))) $(foreach bin,$(GEN_BINS),$(eval $(call ShortcutRule,$(bin),$(BINODIR)))) $(foreach lib,$(GEN_LIBS),$(eval $(call MakeLibrary,$(basename $(lib))))) $(foreach image,$(GEN_IMAGES),$(eval $(call MakeImage,$(basename $(image))))) ############################################################# # Recursion Magic - Don't touch this!! # # Each subtree potentially has an include directory # corresponding to the common APIs applicable to modules # rooted at that subtree. Accordingly, the INCLUDE PATH # of a module can only contain the include directories up # its parent path, and not its siblings # # Required for each makefile to inherit from the parent # ############################################ # 設定標頭檔案路徑 # 把主目錄下的 include標頭檔案包含進來 INCLUDES := $(INCLUDES) -I $(PDIR)include -I $(PDIR)include/$(TARGET) -I $(PDIR)driver_lib/include PDIR := ../$(PDIR) sinclude $(PDIR)Makefile

app下的Makefile

下面我們就來hack一下app/Makefile

#############################################################
# Required variables for each makefile
# Discard this section from all parent makefiles
# Expected variables (with automatic defaults):
#   CSRCS (all "C" files in the dir)
#   SUBDIRS (all subdirs with a Makefile)
#   GEN_LIBS - list of libs to be generated ()
#   GEN_IMAGES - list of object file images to be generated ()
#   GEN_BINS - list of binaries to be generated ()
#   COMPONENTS_xxx - a list of libs/objs in the form
#     subdir/lib to be extracted and rolled up into
#     a generated lib/image xxx.a ()
#

#############################################################

TARGET = eagle
#############################################################
# 選擇debug工程還是release
#FLAVOR = release
FLAVOR = debug

#EXTRA_CCFLAGS += -u

ifndef PDIR # {
GEN_IMAGES= eagle.app.v6.out
GEN_BINS= eagle.app.v6.bin
SPECIAL_MKTARGETS=$(APP_MKTARGETS)

#############################################################
# 子目錄,如果你在app裡新建了一個原始檔目錄,需要新增到這裡
# 否則不會編譯未新增的目錄的原始檔!
SUBDIRS=    \
    user    \
    driver

# 比如添加了一個 network 資料夾,則:
#SUBDIRS=    \
#   user    \
#   driver  \
#   network

endif # } PDIR

APPDIR = .
LDDIR = ../ld

CCFLAGS += -Os

TARGET_LDFLAGS =    \
    -nostdlib       \
    -Wl,-EL         \
    --longcalls     \
    --text-section-literals

#############################################################
# 根據 FLAVOR 變數選擇優化等級
# -O0不優化,-O2中級優化
ifeq ($(FLAVOR),debug)
    TARGET_LDFLAGS += -g -O2
endif

ifeq ($(FLAVOR),release)
    TARGET_LDFLAGS += -g -O0
endif

#############################################################
# 新增靜態連結庫,對應前面 SUBDIRS 變數設定的目錄
# 每一個資料夾裡的原始碼先編譯成對應的靜態庫,然後在進行連結
# 所以如果新增新的原始碼資料夾,也需要在這裡新增對應的靜態庫!
COMPONENTS_eagle.app.v6 =   \
    user/libuser.a          \
    driver/libdriver.a

# 比如新增network:
#COMPONENTS_eagle.app.v6 =   \
#   user/libuser.a          \
#   driver/libdriver.a  \
#   network/libnetwork.a


#############################################################
# 連結引數
# 參考lib資料夾裡的靜態連結庫
# 比如,如果需要使用smartconfig介面
# 只需要新增 -lsmartconfig 即可。
LINKFLAGS_eagle.app.v6 =    \
    -L../lib                \
    -nostdlib               \
    -T$(LD_FILE)            \
    -Wl,--no-check-sections \
    -Wl,--gc-sections       \
    -u call_user_start      \
    -Wl,-static             \
    -Wl,--start-group       \
    -lc                     \
    -lgcc                   \
    -lhal                   \
    -lphy                   \
    -lpp                    \
    -lnet80211              \
    -llwip                  \ # lwip靜態庫,可見ESP8266使用的是lwip協議棧
    -lwpa                   \
    -lcrypto                \
    -lmain                  \ # main靜態庫
    -ljson                  \ # JSON靜態庫
    -lupgrade               \ # OTP線上升級相關庫
    -lssl                   \ # 安全連結SSL靜態庫
    -lpwm                   \ # 有關PWM的靜態庫
    -lsmartconfig           \ # 快速連線smartconfig
    $(DEP_LIBS_eagle.app.v6)\
    -Wl,--end-group

DEPENDS_eagle.app.v6 = \
                $(LD_FILE) \
                $(LDDIR)/eagle.rom.addr.v6.ld

#############################################################
# Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here!
# Generally values applying to a tree are captured in the
#   makefile at its root level - these are then overridden
#   for a subtree within the makefile rooted therein
#

#UNIVERSAL_TARGET_DEFINES =     \

# Other potential configuration flags include:
#   -DTXRX_TXBUF_DEBUG
#   -DTXRX_RXBUF_DEBUG
#   -DWLAN_CONFIG_CCX
CONFIGURATION_DEFINES = -DICACHE_FLASH

DEFINES +=              \
    $(UNIVERSAL_TARGET_DEFINES)    \
    $(CONFIGURATION_DEFINES)

DDEFINES +=             \
    $(UNIVERSAL_TARGET_DEFINES)    \
    $(CONFIGURATION_DEFINES)


#############################################################
# Recursion Magic - Don't touch this!!
#
# Each subtree potentially has an include directory
#   corresponding to the common APIs applicable to modules
#   rooted at that subtree. Accordingly, the INCLUDE PATH
#   of a module can only contain the include directories up
#   its parent path, and not its siblings
#
# Required for each makefile to inherit from the parent
#

#############################################################
# 把當前目錄下的 include 資料夾包含進來
INCLUDES := $(INCLUDES) -I $(PDIR)include

# 把子目錄包含進來
PDIR := ../$(PDIR)

# 把子目錄下的Makefile加進來
# sinclude:以忽略錯誤的方式執行
sinclude $(PDIR)Makefile

.PHONY: FORCE
FORCE:

app/user/下的Makefile

app/Makefile可知,Makefile最後會把子目錄下的Makefile加進來,而且好像還添加了user/libuser.adriver/libdriver.a,但是這些.a檔案怎麼生成我們還不知道。

所以我們來看下app/user/下的Makefile做了一些什麼事情。

#############################################################
# Required variables for each makefile
# Discard this section from all parent makefiles
# Expected variables (with automatic defaults):
#   CSRCS (all "C" files in the dir)
#   SUBDIRS (all subdirs with a Makefile)
#   GEN_LIBS - list of libs to be generated ()
#   GEN_IMAGES - list of images to be generated ()
#   COMPONENTS_xxx - a list of libs/objs in the form
#     subdir/lib to be extracted and rolled up into
#     a generated lib/image xxx.a ()
#

# 仔細閱讀上面英文即可知道是什麼意思了
# 下面語句即是生成 libuser.a 
ifndef PDIR
GEN_LIBS = libuser.a
endif


#############################################################
# Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here!
# Generally values applying to a tree are captured in the
#   makefile at its root level - these are then overridden
#   for a subtree within the makefile rooted therein
#
#DEFINES += 

#############################################################
# Recursion Magic - Don't touch this!!
#
# Each subtree potentially has an include directory
#   corresponding to the common APIs applicable to modules
#   rooted at that subtree. Accordingly, the INCLUDE PATH
#   of a module can only contain the include directories up
#   its parent path, and not its siblings
#
# Required for each makefile to inherit from the parent
#

# 查詢標頭檔案時,進入當前資料夾的 include 資料夾進行查詢(如果有)
INCLUDES := $(INCLUDES) -I $(PDIR)include

# 在當前資料夾的進行查詢
INCLUDES += -I ./

# 在主目錄下的 include/ets/ 資料夾進行查詢
# (實際上本人都沒有找到 include/ets/ 資料夾)
INCLUDES += -I ../../include/ets

PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile

如何新添原始碼資料夾

  1. app/目錄下新建一個資料夾,比如叫network
  2. 然後把app/user/Makefile檔案拷貝過去,修改下面語句:

    ifndef PDIR
    GEN_LIBS = libuser.a
    endif

    改為:

    ifndef PDIR
    GEN_LIBS = libnetwork.a
    endif
  3. 然後編輯app/Makefile,給SUBDIRS變數和COMPONENTS_eagle.app.v6新增對應的檔名稱即可(app/Makefile程式碼分析小節已經有說明);

    
    # ...
    
    
    SUBDIRS=    \
        user    \
        driver
    
    
    # ...
    
    
    COMPONENTS_eagle.app.v6 =   \
    user/libuser.a          \
    driver/libdriver
                
               

    相關推薦

    ESP8266 SDK學習筆記Makefile分析

    主要內容 本章我們來分析SDK中的Makefile,同時學習如何建立自己的原始碼資料夾。 預備知識 一份程式碼工程編譯成二進位制可執行檔案,需要經過四個步驟:預處理、編譯、彙編和連結。 進行編譯需要有編譯器,Linux環境下使用的是gcc,而對應的,

    Unity3D之Mecanim動畫系統學習筆記Animation State

    大致 面板 輸入 jpg any 動畫播放 速度 nsf 顯示 動畫的設置 我們先看看Animation Clip的一些設置: Loop time:動畫是否循環播放。 下面出現了3個大致一樣的選項: Root Transform Rotation:表示為播放動畫

    .net core 2.0學習筆記遷移.net framework 工程到.net core

    編譯 its evel hashtable ref 學習筆記 inline null 創建 在遷移.net core的過程中,第一步就是要把.net framework 工程的目標框架改為.net core2.0,但是官網卻沒有提供轉換工具,需要我們自己動手完成了

    java學習筆記import語法

    employee sign cnblogs java 調用 變量賦值 temp 職位 求職 Import 語法是給編譯器尋找特定類的適當位置的一種方法。 創建一個Employee 類,包括四個實體變量姓名(name),年齡(age),職位(designation)和薪水(s

    HADOOP學習筆記HBase

    系統 唯一性 創建時間 必須 就是 入口 計算 hfile mapreduce HBase簡介 Hbase是分布式、面向列的開源數據庫(其實準確的說是面向列族)。HDFS為Hbase提供可靠的底層數據存儲服務,MapReduce為Hbase提供高性能的計算能力,Zooke

    javaweb學習筆記會話管理1

    目錄 會話管理 1.概念 2.cookie技術 2.1 Cookie一般處理流程 2.2 Cookie類 會話管理 1.概念 一次會話: 開啟瀏覽器 -> 訪問一些伺服器內容 -> 關閉瀏覽器。(瀏覽器A給伺服器傳送請求,訪問web程式,該次會話就

    學習筆記使用K近鄰演算法檢測WebShell

    1.資料蒐集       載入ADFA-LD中正常樣本資料: def load_adfa_training_files(rootdir): x=[] y=[] list = os.listdir(rootdir) for i in

    Scala學習筆記apply方法說明

    調用 我們 val sca 關鍵字 語法糖 方式 rgs 類型 當scala中類或者對象有一個主要用途的時候,apply方法就是一個很好地語法糖。請看下面一個簡單的例子: class Foo(foo: String) {} object Foo { def appl

    Python3學習筆記用Python實現深度優先

    這裡主要是用Python實現下深度優先的概念,由於程式碼寫得比較隨意,就沒有封裝成類,而是寫成一個函式 用一個列表做為實驗資料,模擬成二叉樹結構,用遞迴的方式不斷獲取二叉樹上的左節點,一直到左節點 序號超出列表範圍,然後迴歸獲取右節點,以此來實現深度優先。 以下是程式碼

    安卓開發學習筆記Android Stuidio無法實現隱式Intent是為什麼?

    1 package com.example.lenovo.activitytest; 2 3 import android.support.v7.app.AppCompatActivity; 4 import android.os.Bundle; 5 import android.view

    圖解演算法學習筆記快速排序

    本章內容:學習分而治之,快速排序 1) 示例1: 假設你是農場主,有一小塊土地,你要將這塊地均勻分成方塊,且分出的方塊儘可能大。如何分? 你要將這塊地均勻分成方塊,且分出的方塊要儘可能大。顯然,下面的分法不符合要求。 此時,你應該使用D&C策略(div

    python學習筆記核心模組方法

    核心模組1、__builtin__模組:一、數學運算類abs(x) 求絕對值 1、引數可以是整型,也可以是複數 2、若引數是複數,則返回複數的模 complex([real[, imag]]) 建立一個複數 divmod(a, b) 分別取商和餘數 注意:整型

    各種音視訊編解碼學習詳解之 編解碼學習筆記Mpeg系列——Mpeg 4

       最近在研究音視訊編解碼這一塊兒,看到@bitbit大神寫的【各種音視訊編解碼學習詳解】這篇文章,非常感謝,佩服的五體投地。奈何大神這邊文章太長,在這裡我把它分解成很多小的篇幅,方便閱讀。大神部落格傳送門:https://www.cnblogs.com/skyofbitbit

    Python3+OpenCV學習筆記影象濾波基礎均值、高斯、中值、雙邊

    OpenCV中還可以在影象上進行繪圖操作,由於資料都比較完善,所以附上鍊接,自行參悟。 好了,進入正題。在一張影象,在資料儲存或傳輸的過程中,或多或少都會引入噪聲,常見的影象噪聲如高斯噪聲、瑞利噪聲、椒鹽噪聲等,可參加連結:數字影象噪聲 為了避免噪聲對影象資訊進行干擾或

    SpringBoot學習筆記SpringBoot整合Mybatis-Plus+程式碼生成

    簡介 官網:http://baomidou.oschina.io/mybatis-plus-doc/ 平時業務程式碼不復雜的時候我們寫什麼程式碼寫的最多,就是我們的SQL語句啊,配置那麼多的Mapper.xml,還要配置什麼resultMap這些東西,還要去管理paramtype

    朱老師ARM裸機學習筆記S5PV210啟動過程詳解

    常用器件特性 記憶體: SRAM 靜態記憶體 特點就是容量小、價格高,優點是不需要軟體初始化直接上電就能用 DRAM 動態記憶體 特點就是容量大、價格低,缺點就是上電後不能直接使用,需要軟體初始化後才可以使用。 微

    PostgreSQL學習筆記運算子&函式

    文章目錄 1 運算子&函式 1.1 運算子 1.1.1 算數運算子 1.1.2 關係運算符 1.1.3 邏輯運算子 1.2 函式 1.2.

    PE檔案學習筆記重定位表Relocation Table解析

    1、重定位表的作用 重定位表(Relocation Table)用於在程式載入到記憶體中時,進行記憶體地址的修正。為什麼要進行記憶體地址的修正?我們舉個例子來說:test.exe可執行程式需要三個動態連結庫dll(a.dll,b.dll,c.dll),假設te

    Struts2學習筆記action中訪問request,session以及applicationContext等web資源的方法

    在struts2的action中有時會需要訪問request,session以及applicationContext等web資源,這裡我總結了四種可行的方法,供讀者參考。 (1)使用ActionContext <pre name="code" class="java

    我的Python學習筆記動態新增屬性和方法

    一、動態語言相關概念 1.1 動態語言 在執行時程式碼可以根據某些條件改變自身結構 可以在執行時引進新的函式、物件、甚至程式碼,可以刪除已有的函式等其他結構上的變化 常見的動態語言:Object-C、C#、JavaScript、PHP、Python、Erlang 1.2 動態型別語言 在執行期間檢查資料