From 0f3e7049bc95157fc05e321d09233800124c139f Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 17 Oct 2018 15:55:11 +0200 Subject: [PATCH 1/7] Use utils.AppendIfNotPresent when possible --- create_cmake_rule.go | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/create_cmake_rule.go b/create_cmake_rule.go index 4557ac5d..f36997d8 100644 --- a/create_cmake_rule.go +++ b/create_cmake_rule.go @@ -210,21 +210,21 @@ func extractCompileFlags(ctx *types.Context, receipe string, defines, libs, link for _, arg := range command.Args { if strings.HasPrefix(arg, "-D") { - *defines = appendIfUnique(*defines, arg) + *defines = utils.AppendIfNotPresent(*defines, arg) continue } if strings.HasPrefix(arg, "-l") { - *libs = appendIfUnique(*libs, arg) + *libs = utils.AppendIfNotPresent(*libs, arg) continue } if strings.HasPrefix(arg, "-L") { - *linkDirectories = appendIfUnique(*linkDirectories, strings.TrimPrefix(arg, "-L")) + *linkDirectories = utils.AppendIfNotPresent(*linkDirectories, strings.TrimPrefix(arg, "-L")) continue } if strings.HasPrefix(arg, "-") && !strings.HasPrefix(arg, "-I") && !strings.HasPrefix(arg, "-o") { // HACK : from linkerflags remove MMD (no cache is produced) if !strings.HasPrefix(arg, "-MMD") { - *linkerflags = appendIfUnique(*linkerflags, arg) + *linkerflags = utils.AppendIfNotPresent(*linkerflags, arg) } } } @@ -241,10 +241,3 @@ func findUniqueFoldersRelative(slice []string, base string) string { } return strings.Join(out, " ") } - -func appendIfUnique(slice []string, element string) []string { - if !utils.SliceContains(slice, element) { - slice = append(slice, element) - } - return slice -} From e34e4b72129eb926eef26fa9f5246fffc163049d Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 17 Oct 2018 15:59:14 +0200 Subject: [PATCH 2/7] cmake: Remove '-l' prefix while parsing compile flags --- create_cmake_rule.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/create_cmake_rule.go b/create_cmake_rule.go index f36997d8..6a70b493 100644 --- a/create_cmake_rule.go +++ b/create_cmake_rule.go @@ -168,10 +168,8 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error { // Add SO_PATHS option for libraries not getting found by pkg_config cmakelist += "set(EXTRA_LIBS_DIRS \"\" CACHE STRING \"Additional paths for dynamic libraries\")\n" - for i, lib := range libs { + for _, lib := range libs { // Dynamic libraries should be discovered by pkg_config - lib = strings.TrimPrefix(lib, "-l") - libs[i] = lib cmakelist += "pkg_search_module (" + strings.ToUpper(lib) + " " + lib + ")\n" relLinkDirectories = append(relLinkDirectories, "${"+strings.ToUpper(lib)+"_LIBRARY_DIRS}") } @@ -205,7 +203,7 @@ func canExportCmakeProject(ctx *types.Context) bool { return ctx.BuildProperties[constants.BUILD_PROPERTIES_COMPILER_EXPORT_CMAKE_FLAGS] != "" } -func extractCompileFlags(ctx *types.Context, receipe string, defines, libs, linkerflags, linkDirectories *[]string, logger i18n.Logger) { +func extractCompileFlags(ctx *types.Context, receipe string, defines, dynamicLibs, linkerflags, linkDirectories *[]string, logger i18n.Logger) { command, _ := builder_utils.PrepareCommandForRecipe(ctx, ctx.BuildProperties, receipe, true) for _, arg := range command.Args { @@ -214,11 +212,11 @@ func extractCompileFlags(ctx *types.Context, receipe string, defines, libs, link continue } if strings.HasPrefix(arg, "-l") { - *libs = utils.AppendIfNotPresent(*libs, arg) + *dynamicLibs = utils.AppendIfNotPresent(*dynamicLibs, arg[2:]) continue } if strings.HasPrefix(arg, "-L") { - *linkDirectories = utils.AppendIfNotPresent(*linkDirectories, strings.TrimPrefix(arg, "-L")) + *linkDirectories = utils.AppendIfNotPresent(*linkDirectories, arg[2:]) continue } if strings.HasPrefix(arg, "-") && !strings.HasPrefix(arg, "-I") && !strings.HasPrefix(arg, "-o") { From 5249c59dd923cdb784a4666510641709b64f4a0c Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 17 Oct 2018 16:05:21 +0200 Subject: [PATCH 3/7] cmake: use a single cumulative string to compose the linker start-end group --- create_cmake_rule.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/create_cmake_rule.go b/create_cmake_rule.go index 6a70b493..aafc0d73 100644 --- a/create_cmake_rule.go +++ b/create_cmake_rule.go @@ -168,10 +168,12 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error { // Add SO_PATHS option for libraries not getting found by pkg_config cmakelist += "set(EXTRA_LIBS_DIRS \"\" CACHE STRING \"Additional paths for dynamic libraries\")\n" + linkGroup := "" for _, lib := range libs { // Dynamic libraries should be discovered by pkg_config cmakelist += "pkg_search_module (" + strings.ToUpper(lib) + " " + lib + ")\n" relLinkDirectories = append(relLinkDirectories, "${"+strings.ToUpper(lib)+"_LIBRARY_DIRS}") + linkGroup += " " + lib } cmakelist += "link_directories (" + strings.Join(relLinkDirectories, " ") + " ${EXTRA_LIBS_DIRS})\n" for _, staticLibsFile := range staticLibsFiles { @@ -180,19 +182,20 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error { lib = strings.TrimPrefix(lib, "lib") lib = strings.TrimSuffix(lib, ".a") if !utils.SliceContains(libs, lib) { - libs = append(libs, lib) + linkGroup += " " + lib cmakelist += "add_library (" + lib + " STATIC IMPORTED)\n" location := strings.TrimPrefix(staticLibsFile, cmakeFolder) cmakelist += "set_property(TARGET " + lib + " PROPERTY IMPORTED_LOCATION " + "${PROJECT_SOURCE_DIR}" + location + " )\n" } } + // Include source files // TODO: remove .cpp and .h from libraries example folders cmakelist += "file (GLOB_RECURSE SOURCES core/*.c* lib/*.c* sketch/*.c*)\n" // Compile and link project cmakelist += "add_executable (" + projectName + " ${SOURCES} ${SOURCES_LIBS})\n" - cmakelist += "target_link_libraries( " + projectName + " -Wl,--as-needed -Wl,--start-group " + strings.Join(libs, " ") + " -Wl,--end-group)\n" + cmakelist += "target_link_libraries( " + projectName + " -Wl,--as-needed -Wl,--start-group " + linkGroup + " -Wl,--end-group)\n" utils.WriteFile(cmakeFile, cmakelist) From f809bddb22c8a9377f6ec139d24cf86775d94e36 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 17 Oct 2018 16:08:05 +0200 Subject: [PATCH 4/7] cmake: some variable renames libs -> dynamicLibsFromGccMinusL staticLibsFiles -> staticLibs staticLibsFile -> staticLib --- create_cmake_rule.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/create_cmake_rule.go b/create_cmake_rule.go index aafc0d73..cf44787c 100644 --- a/create_cmake_rule.go +++ b/create_cmake_rule.go @@ -127,12 +127,12 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error { // Extract CFLAGS, CPPFLAGS and LDFLAGS var defines []string var linkerflags []string - var libs []string + var dynamicLibsFromGccMinusL []string var linkDirectories []string - extractCompileFlags(ctx, constants.RECIPE_C_COMBINE_PATTERN, &defines, &libs, &linkerflags, &linkDirectories, logger) - extractCompileFlags(ctx, constants.RECIPE_C_PATTERN, &defines, &libs, &linkerflags, &linkDirectories, logger) - extractCompileFlags(ctx, constants.RECIPE_CPP_PATTERN, &defines, &libs, &linkerflags, &linkDirectories, logger) + extractCompileFlags(ctx, constants.RECIPE_C_COMBINE_PATTERN, &defines, &dynamicLibsFromGccMinusL, &linkerflags, &linkDirectories, logger) + extractCompileFlags(ctx, constants.RECIPE_C_PATTERN, &defines, &dynamicLibsFromGccMinusL, &linkerflags, &linkDirectories, logger) + extractCompileFlags(ctx, constants.RECIPE_CPP_PATTERN, &defines, &dynamicLibsFromGccMinusL, &linkerflags, &linkDirectories, logger) // Extract folders with .h in them for adding in include list var headerFiles []string @@ -141,9 +141,9 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error { foldersContainingDotH := findUniqueFoldersRelative(headerFiles, cmakeFolder) // Extract folders with .a in them for adding in static libs paths list - var staticLibsFiles []string + var staticLibs []string isStaticLib := func(ext string) bool { return DOTAEXTENSION[ext] } - utils.FindFilesInFolder(&staticLibsFiles, cmakeFolder, isStaticLib, true) + utils.FindFilesInFolder(&staticLibs, cmakeFolder, isStaticLib, true) // Generate the CMakeLists global file @@ -169,22 +169,22 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error { cmakelist += "set(EXTRA_LIBS_DIRS \"\" CACHE STRING \"Additional paths for dynamic libraries\")\n" linkGroup := "" - for _, lib := range libs { + for _, lib := range dynamicLibsFromGccMinusL { // Dynamic libraries should be discovered by pkg_config cmakelist += "pkg_search_module (" + strings.ToUpper(lib) + " " + lib + ")\n" relLinkDirectories = append(relLinkDirectories, "${"+strings.ToUpper(lib)+"_LIBRARY_DIRS}") linkGroup += " " + lib } cmakelist += "link_directories (" + strings.Join(relLinkDirectories, " ") + " ${EXTRA_LIBS_DIRS})\n" - for _, staticLibsFile := range staticLibsFiles { + for _, staticLib := range staticLibs { // Static libraries are fully configured - lib := filepath.Base(staticLibsFile) + lib := filepath.Base(staticLib) lib = strings.TrimPrefix(lib, "lib") lib = strings.TrimSuffix(lib, ".a") - if !utils.SliceContains(libs, lib) { + if !utils.SliceContains(dynamicLibsFromGccMinusL, lib) { linkGroup += " " + lib cmakelist += "add_library (" + lib + " STATIC IMPORTED)\n" - location := strings.TrimPrefix(staticLibsFile, cmakeFolder) + location := strings.TrimPrefix(staticLib, cmakeFolder) cmakelist += "set_property(TARGET " + lib + " PROPERTY IMPORTED_LOCATION " + "${PROJECT_SOURCE_DIR}" + location + " )\n" } } From 3a72f028573f80e3a993b2bf4e25ffc5d22f8057 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 17 Oct 2018 16:11:57 +0200 Subject: [PATCH 5/7] cmake: moved some lines for better readability --- create_cmake_rule.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/create_cmake_rule.go b/create_cmake_rule.go index cf44787c..2a9c8326 100644 --- a/create_cmake_rule.go +++ b/create_cmake_rule.go @@ -76,18 +76,19 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error { coreFolder := filepath.Join(cmakeFolder, "core") cmakeFile := filepath.Join(cmakeFolder, "CMakeLists.txt") - // Copy used libraries in the correct folder extensions := func(ext string) bool { return VALID_EXPORT_EXTENSIONS[ext] } + staticLibsExtensions := func(ext string) bool { return DOTAEXTENSION[ext] } for _, library := range ctx.ImportedLibraries { + // Copy used libraries in the correct folder libFolder := filepath.Join(libBaseFolder, library.Name) + mcu := ctx.BuildProperties[constants.BUILD_PROPERTIES_BUILD_MCU] utils.CopyDir(library.Folder, libFolder, extensions) // Remove examples folder if _, err := os.Stat(filepath.Join(libFolder, "examples")); err == nil { os.RemoveAll(filepath.Join(libFolder, "examples")) } - // Remove stray folders contining incompatible libraries - staticLibsExtensions := func(ext string) bool { return DOTAEXTENSION[ext] } - mcu := ctx.BuildProperties[constants.BUILD_PROPERTIES_BUILD_MCU] + + // Remove stray folders contining incompatible or not needed libraries archives var files []string utils.FindFilesInFolder(&files, filepath.Join(libFolder, "src"), staticLibsExtensions, true) for _, file := range files { From d9d6467514a68a123fc9ea94459e60a1b7677977 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 17 Oct 2018 16:14:26 +0200 Subject: [PATCH 6/7] cmake: removed redundant function --- create_cmake_rule.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/create_cmake_rule.go b/create_cmake_rule.go index 2a9c8326..e80e3209 100644 --- a/create_cmake_rule.go +++ b/create_cmake_rule.go @@ -143,8 +143,7 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error { // Extract folders with .a in them for adding in static libs paths list var staticLibs []string - isStaticLib := func(ext string) bool { return DOTAEXTENSION[ext] } - utils.FindFilesInFolder(&staticLibs, cmakeFolder, isStaticLib, true) + utils.FindFilesInFolder(&staticLibs, cmakeFolder, staticLibsExtensions, true) // Generate the CMakeLists global file From 217bd60a34d73297dd8dc36005f5a880b8eea20e Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 17 Oct 2018 16:14:56 +0200 Subject: [PATCH 7/7] cmake: Allow dynamic linking of libraries This commit introduce a way for library authors to force the builder to output a cmake build script with a library linked dynamically. The trick is to add a file named arduino_builder.properties with the following key: cmake.pkg_config=lib1 lib2 lib3 ... By doing so, the lib archives (.a) in the library are ignored and a bunch of "pkg_search_module" rows are added to the CMakeList.txt for the specified "lib1" "lib2" "lib3". The corresponding flags in "link_directories" and "target_link_libraries" directives are added as well. The above trick does affect only the cmake export, the normal build of the arduino-builder is unchanged. --- create_cmake_rule.go | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/create_cmake_rule.go b/create_cmake_rule.go index e80e3209..9d316457 100644 --- a/create_cmake_rule.go +++ b/create_cmake_rule.go @@ -35,6 +35,8 @@ import ( "path/filepath" "strings" + "github.com/arduino/go-properties-map" + "github.com/arduino/arduino-builder/builder_utils" "github.com/arduino/arduino-builder/constants" "github.com/arduino/arduino-builder/i18n" @@ -42,7 +44,7 @@ import ( "github.com/arduino/arduino-builder/utils" ) -var VALID_EXPORT_EXTENSIONS = map[string]bool{".h": true, ".c": true, ".hpp": true, ".hh": true, ".cpp": true, ".s": true, ".a": true} +var VALID_EXPORT_EXTENSIONS = map[string]bool{".h": true, ".c": true, ".hpp": true, ".hh": true, ".cpp": true, ".s": true, ".a": true, ".properties": true} var DOTHEXTENSION = map[string]bool{".h": true, ".hh": true, ".hpp": true} var DOTAEXTENSION = map[string]bool{".a": true} @@ -76,6 +78,7 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error { coreFolder := filepath.Join(cmakeFolder, "core") cmakeFile := filepath.Join(cmakeFolder, "CMakeLists.txt") + dynamicLibsFromPkgConfig := map[string]bool{} extensions := func(ext string) bool { return VALID_EXPORT_EXTENSIONS[ext] } staticLibsExtensions := func(ext string) bool { return DOTAEXTENSION[ext] } for _, library := range ctx.ImportedLibraries { @@ -83,6 +86,19 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error { libFolder := filepath.Join(libBaseFolder, library.Name) mcu := ctx.BuildProperties[constants.BUILD_PROPERTIES_BUILD_MCU] utils.CopyDir(library.Folder, libFolder, extensions) + + // Read cmake options if available + isStaticLib := true + if cmakeOptions, err := properties.Load(filepath.Join(libFolder, "src", mcu, "arduino_builder.properties")); err == nil { + // If the library can be linked dynamically do not copy the library folder + if pkgs, ok := cmakeOptions["cmake.pkg_config"]; ok { + isStaticLib = false + for _, pkg := range strings.Split(pkgs, " ") { + dynamicLibsFromPkgConfig[pkg] = true + } + } + } + // Remove examples folder if _, err := os.Stat(filepath.Join(libFolder, "examples")); err == nil { os.RemoveAll(filepath.Join(libFolder, "examples")) @@ -92,8 +108,9 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error { var files []string utils.FindFilesInFolder(&files, filepath.Join(libFolder, "src"), staticLibsExtensions, true) for _, file := range files { - if !strings.Contains(filepath.Dir(file), mcu) { - os.RemoveAll(filepath.Dir(file)) + staticLibDir := filepath.Dir(file) + if !isStaticLib || !strings.Contains(staticLibDir, mcu) { + os.RemoveAll(staticLibDir) } } } @@ -175,6 +192,11 @@ func (s *ExportProjectCMake) Run(ctx *types.Context) error { relLinkDirectories = append(relLinkDirectories, "${"+strings.ToUpper(lib)+"_LIBRARY_DIRS}") linkGroup += " " + lib } + for lib := range dynamicLibsFromPkgConfig { + cmakelist += "pkg_search_module (" + strings.ToUpper(lib) + " " + lib + ")\n" + relLinkDirectories = append(relLinkDirectories, "${"+strings.ToUpper(lib)+"_LIBRARY_DIRS}") + linkGroup += " ${" + strings.ToUpper(lib) + "_LIBRARIES}" + } cmakelist += "link_directories (" + strings.Join(relLinkDirectories, " ") + " ${EXTRA_LIBS_DIRS})\n" for _, staticLib := range staticLibs { // Static libraries are fully configured