From 5e057f38b989a49554282e4c071f836564ce2dbd Mon Sep 17 00:00:00 2001 From: aviralgarg05 Date: Sun, 2 Aug 2026 22:52:39 +0530 Subject: [PATCH] build: add declarative shared library support Add Library.mk for declarative shared-library builds. Reuse the compiler-runtime lookup shared with Application.mk and cover multi-source libraries with sotest. Signed-off-by: aviralgarg05 --- Application.mk | 9 +- Library.mk | 185 +++++++++++++++++++++++ Make.defs | 15 ++ examples/sotest/modprint/Makefile | 9 +- examples/sotest/sotest/CMakeLists.txt | 9 +- examples/sotest/sotest/Makefile | 9 +- examples/sotest/sotest/sotest.c | 8 - examples/sotest/sotest/sotest_messages.c | 40 +++++ 8 files changed, 257 insertions(+), 27 deletions(-) create mode 100644 Library.mk create mode 100644 examples/sotest/sotest/sotest_messages.c diff --git a/Application.mk b/Application.mk index bc83121a9..8606e5d3a 100644 --- a/Application.mk +++ b/Application.mk @@ -62,14 +62,7 @@ LDLIBS += $(call CONVERT_PATH,$(BIN)) # This should be linked after libapps. Consider that mbedtls in libapps # uses __udivdi3. ifeq ($(BUILD_MODULE),y) - # Revisit: This only works for gcc and clang. - # Do other compilers have similar? - COMPILER_RT_LIB = $(shell $(CC) $(ARCHCPUFLAGS) --print-libgcc-file-name) - ifeq ($(wildcard $(COMPILER_RT_LIB)),) - # if "--print-libgcc-file-name" unable to find the correct libgcc PATH - # then go ahead and try "--print-file-name" - COMPILER_RT_LIB := $(wildcard $(shell $(CC) $(ARCHCPUFLAGS) --print-file-name $(notdir $(COMPILER_RT_LIB)))) - endif + COMPILER_RT_LIB := $(call FIND_COMPILER_RT_LIB) LDLIBS += $(COMPILER_RT_LIB) endif diff --git a/Library.mk b/Library.mk new file mode 100644 index 000000000..9dd7ca197 --- /dev/null +++ b/Library.mk @@ -0,0 +1,185 @@ +############################################################################ +# apps/Library.mk +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +# Library.mk is the NuttX equivalent of Android's BUILD_SHARED_LIBRARY. A +# component Makefile includes Make.defs, declares LOCAL_MODULE and +# LOCAL_SRC_FILES, then includes this file. NuttX invokes each component in +# a separate recursive make, so module variables cannot leak between +# components and an equivalent of Android's CLEAR_VARS is not needed. + +LOCAL_PATH ?= $(CURDIR) + +ifeq ($(strip $(LOCAL_MODULE)),) + $(error LOCAL_MODULE must name the shared library) +endif + +ifeq ($(strip $(LOCAL_SRC_FILES)),) + $(error LOCAL_SRC_FILES must list at least one C or C++ source file) +endif + +LOCAL_C_SRCS := $(filter %.c,$(LOCAL_SRC_FILES)) +LOCAL_CC_SRCS := $(filter %.cc,$(LOCAL_SRC_FILES)) +LOCAL_CPP_SRCS := $(filter %.cpp,$(LOCAL_SRC_FILES)) +LOCAL_CXX_SRCS := $(filter %.cxx,$(LOCAL_SRC_FILES)) +LOCAL_SRCS := $(LOCAL_C_SRCS) $(LOCAL_CC_SRCS) $(LOCAL_CPP_SRCS) \ + $(LOCAL_CXX_SRCS) + +ifneq ($(words $(LOCAL_SRCS)),$(words $(LOCAL_SRC_FILES))) + $(error LOCAL_SRC_FILES currently supports only .c, .cc, .cpp, and .cxx) +endif + +# The GNU make CURDIR always uses forward slashes. Convert it for native +# Windows builds before deriving the suffix used for intermediate objects. + +ifeq ($(CONFIG_WINDOWS_NATIVE),y) + LOCAL_CWD := $(strip ${shell echo %CD% | cut -d: -f2}) +else + LOCAL_CWD := $(CURDIR) +endif + +LOCAL_SUFFIX := $(subst $(DELIM),.,$(LOCAL_CWD)) +LOCAL_PREFIX ?= + +LOCAL_C_OBJS := $(LOCAL_C_SRCS:%=$(LOCAL_PREFIX)%$(LOCAL_SUFFIX)$(OBJEXT)) +LOCAL_CC_OBJS := $(LOCAL_CC_SRCS:%=$(LOCAL_PREFIX)%$(LOCAL_SUFFIX)$(OBJEXT)) +LOCAL_CPP_OBJS := $(LOCAL_CPP_SRCS:%=$(LOCAL_PREFIX)%$(LOCAL_SUFFIX)$(OBJEXT)) +LOCAL_CXX_OBJS := $(LOCAL_CXX_SRCS:%=$(LOCAL_PREFIX)%$(LOCAL_SUFFIX)$(OBJEXT)) +LOCAL_OBJS := $(LOCAL_C_OBJS) $(LOCAL_CC_OBJS) $(LOCAL_CPP_OBJS) \ + $(LOCAL_CXX_OBJS) + +# Keep the historical NuttX module filename by default. A component may set +# LOCAL_MODULE_FILENAME (for example, libexample.so) when a suffix is part of +# its external interface. + +LOCAL_MODULE_FILENAME ?= $(LOCAL_MODULE) +LOCAL_MODULE_PATH := $(BINDIR)$(DELIM)$(LOCAL_MODULE_FILENAME) + +LOCAL_CFLAGS ?= +LOCAL_CXXFLAGS ?= +LOCAL_LDFLAGS ?= +LOCAL_LDLIBS ?= + +LOCAL_COMPILER_RT_LIB := $(call FIND_COMPILER_RT_LIB) + +DEPPATH += --dep-path $(LOCAL_PATH) +DEPPATH += --obj-path . + +VPATH += :$(LOCAL_PATH) + +.PHONY: all clean context depend distclean install postinstall register + +all:: $(LOCAL_PREFIX).built + @: + +define LOCAL_COMPILE_C + $(ECHO_BEGIN)"CC: $1 " + $(Q) $(MODULECC) -c $(CMODULEFLAGS) $(LOCAL_CFLAGS) \ + $($(strip $1)_CELFFLAGS) $1 -o $2 + $(ECHO_END) +endef + +define LOCAL_COMPILE_CXX + $(ECHO_BEGIN)"CXX: $1 " + $(Q) $(CXX) -c $(CXXMODULEFLAGS) $(LOCAL_CXXFLAGS) \ + $($(strip $1)_CXXELFFLAGS) $1 -o $2 + $(ECHO_END) +endef + +$(LOCAL_C_OBJS): $(LOCAL_PREFIX)%.c$(LOCAL_SUFFIX)$(OBJEXT): %.c + $(call LOCAL_COMPILE_C,$<,$@) + +$(LOCAL_CC_OBJS): $(LOCAL_PREFIX)%.cc$(LOCAL_SUFFIX)$(OBJEXT): %.cc + $(call LOCAL_COMPILE_CXX,$<,$@) + +$(LOCAL_CPP_OBJS): $(LOCAL_PREFIX)%.cpp$(LOCAL_SUFFIX)$(OBJEXT): %.cpp + $(call LOCAL_COMPILE_CXX,$<,$@) + +$(LOCAL_CXX_OBJS): $(LOCAL_PREFIX)%.cxx$(LOCAL_SUFFIX)$(OBJEXT): %.cxx + $(call LOCAL_COMPILE_CXX,$<,$@) + +$(LOCAL_PREFIX).built: $(LOCAL_OBJS) + $(Q) touch $@ + +$(LOCAL_MODULE_PATH): $(LOCAL_OBJS) + $(ECHO_BEGIN)"LD: $@ " + $(Q) mkdir -p $(BINDIR) + $(Q) $(MODULELD) $(LDMODULEFLAGS) $(LDMAP) $(LDLIBPATH) \ + $(LOCAL_LDFLAGS) $^ $(LDSTARTGROUP) $(LOCAL_LDLIBS) \ + $(LOCAL_COMPILER_RT_LIB) $(LDENDGROUP) -o \ + $(call CONVERT_PATH,$@) + $(ECHO_END) +ifneq ($(CONFIG_DEBUG_SYMBOLS),) + $(Q) mkdir -p $(BINDIR_DEBUG) + $(Q) cp $@ $(BINDIR_DEBUG) + $(Q) $(MODULESTRIP) $(NX_KEEP) $@ +endif + +install:: $(LOCAL_MODULE_PATH) + @: + +context:: + @: + +register:: + @: + +postinstall:: + @: + +$(LOCAL_PREFIX).depend: Makefile $(LOCAL_SRC_FILES) $(DEPCONFIG) + $(shell echo "# Gen Make.dep automatically" >$(LOCAL_PREFIX)Make.dep) + $(if $(LOCAL_C_SRCS), \ + $(shell $(MKDEP) $(DEPPATH) \ + --obj-suffix .c$(LOCAL_SUFFIX)$(OBJEXT) "$(MODULECC)" -- \ + $(CMODULEFLAGS) $(LOCAL_CFLAGS) -- $(LOCAL_C_SRCS) \ + >>$(LOCAL_PREFIX)Make.dep)) + $(if $(LOCAL_CC_SRCS), \ + $(shell $(MKDEP) $(DEPPATH) \ + --obj-suffix .cc$(LOCAL_SUFFIX)$(OBJEXT) "$(CXX)" -- \ + $(CXXMODULEFLAGS) $(LOCAL_CXXFLAGS) -- $(LOCAL_CC_SRCS) \ + >>$(LOCAL_PREFIX)Make.dep)) + $(if $(LOCAL_CPP_SRCS), \ + $(shell $(MKDEP) $(DEPPATH) \ + --obj-suffix .cpp$(LOCAL_SUFFIX)$(OBJEXT) "$(CXX)" -- \ + $(CXXMODULEFLAGS) $(LOCAL_CXXFLAGS) -- $(LOCAL_CPP_SRCS) \ + >>$(LOCAL_PREFIX)Make.dep)) + $(if $(LOCAL_CXX_SRCS), \ + $(shell $(MKDEP) $(DEPPATH) \ + --obj-suffix .cxx$(LOCAL_SUFFIX)$(OBJEXT) "$(CXX)" -- \ + $(CXXMODULEFLAGS) $(LOCAL_CXXFLAGS) -- $(LOCAL_CXX_SRCS) \ + >>$(LOCAL_PREFIX)Make.dep)) + $(Q) touch $@ + +depend:: $(LOCAL_PREFIX).depend + @: + +clean:: + $(call DELFILE,$(LOCAL_PREFIX).built) + $(call DELFILE,$(LOCAL_OBJS)) + $(call DELFILE,$(LOCAL_MODULE_PATH)) + $(call DELFILE,$(BINDIR_DEBUG)$(DELIM)$(LOCAL_MODULE_FILENAME)) + +distclean:: clean + $(call DELFILE,$(LOCAL_PREFIX)Make.dep) + $(call DELFILE,$(LOCAL_PREFIX).depend) + +-include $(LOCAL_PREFIX)Make.dep diff --git a/Make.defs b/Make.defs index ab79ce71c..416099d7a 100644 --- a/Make.defs +++ b/Make.defs @@ -68,6 +68,21 @@ LIBPATH ?= $(TOPDIR)$(DELIM)staging BINDIR ?= $(APPDIR)$(DELIM)bin BINDIR_DEBUG ?= $(APPDIR)$(DELIM)bin_debug +# Android.mk-style shared library build primitive + +BUILD_SHARED_LIBRARY ?= $(APPDIR)$(DELIM)Library.mk + +# Locate the compiler runtime used by loadable modules. GCC and Clang +# support these queries; other compilers may need an equivalent lookup. + +define FIND_COMPILER_RT_LIB +$(or $(wildcard $(shell $(CC) $(ARCHCPUFLAGS) \ + --print-libgcc-file-name)), \ + $(wildcard $(shell $(CC) $(ARCHCPUFLAGS) --print-file-name \ + $(notdir $(shell $(CC) $(ARCHCPUFLAGS) \ + --print-libgcc-file-name))))) +endef + # The final build target BIN ?= $(APPDIR)$(DELIM)libapps$(LIBEXT) diff --git a/examples/sotest/modprint/Makefile b/examples/sotest/modprint/Makefile index 81f5c2c53..85720dec0 100644 --- a/examples/sotest/modprint/Makefile +++ b/examples/sotest/modprint/Makefile @@ -22,9 +22,8 @@ include $(APPDIR)/Make.defs -PROGNAME = modprint -DYNLIB = y +LOCAL_PATH := $(CURDIR) +LOCAL_MODULE := modprint +LOCAL_SRC_FILES := modprint.c -MAINSRC = modprint.c - -include $(APPDIR)/Application.mk +include $(BUILD_SHARED_LIBRARY) diff --git a/examples/sotest/sotest/CMakeLists.txt b/examples/sotest/sotest/CMakeLists.txt index d4f30c1c5..cee83b15b 100644 --- a/examples/sotest/sotest/CMakeLists.txt +++ b/examples/sotest/sotest/CMakeLists.txt @@ -21,5 +21,12 @@ # ############################################################################## if(CONFIG_EXAMPLES_SOTEST) - nuttx_add_application(NAME sotest SRCS sotest.c DYNLIB y) + nuttx_add_application( + NAME + sotest + SRCS + sotest.c + sotest_messages.c + DYNLIB + y) endif() diff --git a/examples/sotest/sotest/Makefile b/examples/sotest/sotest/Makefile index dfbec74a1..f3c706db2 100644 --- a/examples/sotest/sotest/Makefile +++ b/examples/sotest/sotest/Makefile @@ -22,9 +22,8 @@ include $(APPDIR)/Make.defs -PROGNAME = sotest -DYNLIB = y +LOCAL_PATH := $(CURDIR) +LOCAL_MODULE := sotest +LOCAL_SRC_FILES := sotest.c sotest_messages.c -MAINSRC = sotest.c - -include $(APPDIR)/Application.mk +include $(BUILD_SHARED_LIBRARY) diff --git a/examples/sotest/sotest/sotest.c b/examples/sotest/sotest/sotest.c index ff825cbac..089dfb76e 100644 --- a/examples/sotest/sotest/sotest.c +++ b/examples/sotest/sotest/sotest.c @@ -46,14 +46,6 @@ void modprint(FAR const char *fmt, ...) printf_like(1, 2); * Private Function Prototypes ****************************************************************************/ -/**************************************************************************** - * Private Data - ****************************************************************************/ - -visibility_default const char g_msg1[] = "Hello to you too!"; -visibility_default const char g_msg2[] = "Not so bad so far."; -visibility_default const char g_msg3[] = "Yes, don't be a stranger!"; - /**************************************************************************** * Private Functions ****************************************************************************/ diff --git a/examples/sotest/sotest/sotest_messages.c b/examples/sotest/sotest/sotest_messages.c new file mode 100644 index 000000000..d867c1c77 --- /dev/null +++ b/examples/sotest/sotest/sotest_messages.c @@ -0,0 +1,40 @@ +/**************************************************************************** + * apps/examples/sotest/sotest/sotest_messages.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +visibility_default const char g_msg1[] = "Hello to you too!"; +visibility_default const char g_msg2[] = "Not so bad so far."; +visibility_default const char g_msg3[] = "Yes, don't be a stranger!"; + +/**************************************************************************** + * Public Functions + ****************************************************************************/