cmake_minimum_required(VERSION 3.10) #put your files in sub folder of src dep res project(Proj) #turn on source_group filter set_property(GLOBAL PROPERTY USE_FOLDERS ON) #utility functions macro(SubDirList result curdir) file(GLOB children RELATIVE ${curdir} ${curdir}/*) set(dirlist "") foreach(child ${children}) if(IS_DIRECTORY ${curdir}/${child}) list(APPEND dirlist ${child}) endif() endforeach() set(${result} ${dirlist}) endmacro() macro(create_source_tree any_file) set(_source_root ${CMAKE_CURRENT_SOURCE_DIR}) foreach(_tree_file ${${any_file}}) #change to relative path string(REGEX REPLACE ${_source_root}/* "" _tree_file_path_relative ${_tree_file}) #get file name without path string(REGEX REPLACE ".*/" "" _tree_file_name ${_tree_file_path_relative}) #remove file name from path string string(REGEX REPLACE /${_tree_file_name} "" _tree_file_path_relative_pure ${_tree_file_path_relative}) #change / into \\ to repesent a group path string(REGEX REPLACE "/" "\\\\\\\\" _tree_file_path_group ${_tree_file_path_relative_pure}) string(APPEND _tree_file_path_group "\\\\") #message(STATUS ${_tree_file_path_group}) #message(STATUS ${_tree_file}) source_group(${_tree_file_path_group} FILES ${_tree_file}) #all pro_tree__all_files must be added to add_executable, inorder to get shown in filter endforeach(_tree_file) endmacro(create_source_tree) #set output path of exe set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}/bin) # folder auto created if not exist #include files #layout format:libname # include # lib # bin #put .c .cpp files under src/ SubDirList(subs ${CMAKE_CURRENT_SOURCE_DIR}/dep) foreach(subdir ${subs}) set(deal "dep/") string(APPEND deal ${subdir} "/include/") list(APPEND includelist ${deal}) #message(STATUS ${deal}) endforeach() include_directories(${includelist}) #include all folders under src file(GLOB_RECURSE all LIST_DIRECTORIES true RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} src/*) file(GLOB_RECURSE dataonly LIST_DIRECTORIES false RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} src/*) foreach(data ${dataonly}) list(FIND all ${data} pos) if(pos GREATER -1) list(REMOVE_ITEM all ${data}) endif() endforeach(data) include_directories(${all}) #copy dll files to bin file(GLOB_RECURSE dynamiclibs dep/*.dll) foreach(dll ${dynamiclibs}) file(COPY ${dll} DESTINATION ${EXECUTABLE_OUTPUT_PATH}) #复制到编译根目录中,因为VS编译的工作目录为.vcxproj所在文件夹 #在vs里调试运行时,会到这里来找dll file(COPY ${dll} DESTINATION ${CMAKE_BINARY_DIR}) endforeach() #dependend lib file(GLOB_RECURSE staticlibs dep/*.lib) link_libraries(${staticlibs}) #resource files file(COPY res/ DESTINATION ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}/res) #program source files file(GLOB_RECURSE sourcefiles src/* ) #add exe add_executable(${CMAKE_PROJECT_NAME} ${sourcefiles}) ################################################################ #创建filter tree 开始 ################################################################ #关于将文件添加到filter中 #有个source_group TREE,还没尝试。手动一个一个添加。 #万恶之源 #1#最重要的条件:想出现在filter中,必须添加在某个target的source中。 #可用target_sources指定。 #2#有些库写的比较脏,例如glm,其中有个文件有个空的main函数,若将其 #添加到target的source中会导致main重复。 #再如boost中的asio,只使用头文件模式的时候,将其添加到target的source中 #也会导致出错。 #不给这些库添加filter即可。因为想出现在filter中,必须添加到target的source中。 #但添加进去又会出错... #不添加filter的文件夹 #这里只控制dep src 下的直接子目录,所以只可添加这些文件夹下的子文件夹 set(RubDirList dep/boost dep/glm ) #从filter中排除间接子目录 #有些库添加到target_sources会出错,例如boost中的asio,不为其建立filter即可 #添加方式:dep/boost/include/boost/asio set(RubbishExcludeFromFilterList ) SubDirList(treedir1 ${CMAKE_CURRENT_SOURCE_DIR}/dep)#依赖库 foreach(depdir ${treedir1}) string(PREPEND depdir "dep/") string(APPEND depdir "/include") list(APPEND tempdepdir ${depdir}) endforeach() set(treedir1 ${tempdepdir}) SubDirList(treedir2 ${CMAKE_CURRENT_SOURCE_DIR}/src)#程序文件 foreach(srcdir ${treedir2}) string(PREPEND srcdir "src/") list(APPEND tempsrcdir ${srcdir}) endforeach() set(treedir2 ${tempsrcdir}) set(treedirall ${treedir1} ${treedir2}) #排除直接子文件夹 foreach(projitem ${treedirall}) foreach(rubbish ${RubDirList}) set(ThisTmpString "") string(APPEND ThisTmpString ".*" ${rubbish} ".*") if (${projitem} MATCHES ${ThisTmpString}) list(REMOVE_ITEM treedirall ${projitem}) endif(${projitem} MATCHES ${ThisTmpString}) endforeach() endforeach() #获取所有文件 foreach(treedirone ${treedirall}) string(APPEND treedirone "/*") file(GLOB_RECURSE pro_tree__tmpsource ${treedirone} ) list(APPEND pro_tree__all_files ${pro_tree__tmpsource}) endforeach() #排除间接子文件夹 foreach(projitem ${pro_tree__all_files}) foreach(rubbish ${RubbishExcludeFromFilterList}) set(ThisTmpString "") string(APPEND ThisTmpString ".*" ${rubbish} ".*") if (${projitem} MATCHES ${ThisTmpString}) list(REMOVE_ITEM pro_tree__all_files ${projitem}) endif(${projitem} MATCHES ${ThisTmpString}) endforeach() endforeach() #必须的一个步骤 target_sources(${CMAKE_PROJECT_NAME} PRIVATE ${pro_tree__all_files}) create_source_tree(pro_tree__all_files) ################################################################ #创建filter tree 结束 ################################################################