correct way to organize application source files in subdirectories

558 views
Skip to first unread message

Matias N.

unread,
May 8, 2018, 9:12:30 AM5/8/18
to nu...@googlegroups.com
Hello,
I have asked something similar in the past but since the yahoo group seems to be nonexisting I felt to ask about it again since I'm having other problems with this.

I'm currently writing my own set of apps in apps/external/ organized as apps/external/app1, apps/external/app2, etc. Each app has the following structure:

ls app/
Kconfig  Make.dep  Makefile  src

Inside src, the source files may be organized in subdirectories. For this to work, I defined my CXXSRCS variable including the path relative to the application root ("app") in this case. The first problem was that depend rules did not work correctly since, for some reason, the left-hand side of depend rules lacked the complete path and I had to do the following to fix it in my app Makefile:

depend: .depend
        @sed -ri 's%^(.*): (\S+/)?%\2\1: \2%g' Make.dep

So far I haven't questioned much about this setup but now I realized that when doing "make clean" from nuttx/ (or, more specifically make apps_clean), my object files are not deleted. After going deep into the build system I found that only object files at the application directory are removed, with a step such as "rm *.o".
This was unexpected since I thought that, since in Application.mk the list of object files is built (in OBJS variable) this could be used to remove all object files, irregardless of their location inside the application directory. Again, to "fix" this, I did something like:

clean: extraclean
extraclean:
        rm -f $(OBJS)

(if I redefined clean I got some warnings and it also didn't feel right to override a NuttX rule).

So, my question is: is there a better workflow I should be using to expose my application with subdirectories to NuttX build system? Alternatively, would it be possible/reasonable to add the removal of $(OBJS) as part of the apps build system? Regarding the Make.dep generation I do not even fully understand why it is happening since, again, I would expect the build system to have the required information.

Best,
Matias

patacongo

unread,
May 8, 2018, 10:00:00 AM5/8/18
to NuttX

Inside src, the source files may be organized in subdirectories. For this to work, I defined my CXXSRCS variable including the path relative to the application root ("app") in this case. The first problem was that depend rules did not work correctly since, for some reason, the left-hand side of depend rules lacked the complete path and I had to do the following to fix it in my app Makefile:

Sounds like you are not using VPATH as is done in other Makefiles.  If the entire make is performed at the top level, then:

1. VPATH is used to identify the path to the source in a sub-directory,
2. Make.dep will contain the relative PATH as determined by VPATH
3. All of the .o file will be at the top level and can be removed with the rm *.o

If you are following a different pattern they, yes, you will introduce new complexities.  Those should all be solvable, but you will need to invent your own solution.

Greg

Matias N.

unread,
May 8, 2018, 10:49:29 AM5/8/18
to nu...@googlegroups.com
Ok, so I understand that VPATH allows you to list paths where source files should be expected, right? Should I then add "src" to my VPATH file with:

VPATH += src

from my application Makefile? I tried the previous line and it does not seem that "clean" goes into src/
--
You received this message because you are subscribed to the Google Groups "NuttX" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nuttx+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Matias N.

unread,
May 8, 2018, 10:53:48 AM5/8/18
to nu...@googlegroups.com
For completeness, here's my application Makefile:

-include $(TOPDIR)/Make.defs

ASRCS =
CSRCS =
CXXSRCS = src/drive_controller.cxx \
          src/communicator.cxx  \
          src/buzzer.cxx \
          src/robot.cxx \
          src/battery_monitor.cxx \
          src/lib/sonar.cxx \
          src/lib/pid.cxx

MAINSRC = src/main.cxx


PROGNAME = rover$(EXEEXT)
APPNAME = rover
PRIORITY = SCHED_PRIORITY_DEFAULT
STACKSIZE = 16384

CXXFLAGS += -I$(APPDIR)/external/rover/src/ -I$(APPDIR)/external/empl/src/ -std=c++14
VPATH += src

include $(APPDIR)/Application.mk

patacongo

unread,
May 8, 2018, 11:04:14 AM5/8/18
to NuttX
CXXSRCS = src/drive_controller.cxx \
          src/communicator.cxx  \
          src/buzzer.cxx \
          src/robot.cxx \
          src/battery_monitor.cxx \
          src/lib/sonar.cxx \
          src/lib/pid.cxx

MAINSRC = src/main.cxx

You would also have to remove the src/ from the beginning of each of these files.

michal....@bofc.pl

unread,
May 8, 2018, 11:05:51 AM5/8/18
to Matias N., nu...@googlegroups.com
On 2018-05-08 11:53:45, Matias N. wrote:
> For completeness, here's my application Makefile:
>
> -include $(TOPDIR)/Make.defs
>
> ASRCS =
> CSRCS =
> CXXSRCS = src/drive_controller.cxx \
> src/communicator.cxx \
> src/buzzer.cxx \
> src/robot.cxx \
> src/battery_monitor.cxx \
> src/lib/sonar.cxx \
> src/lib/pid.cxx
>
> MAINSRC = src/main.cxx
>
>
> PROGNAME = rover$(EXEEXT)
> APPNAME = rover
> PRIORITY = SCHED_PRIORITY_DEFAULT
> STACKSIZE = 16384
>
> CXXFLAGS += -I$(APPDIR)/external/rover/src/ -
> I$(APPDIR)/external/empl/src/ -std=c++14VPATH += src
>
> include $(APPDIR)/Application.mk

Hmm, I am not entirely sure if that is relevant, but I recently added program
that has nested sources so CSRCS are similar to what you have:

SRCS = embedlog/src/el-options.c \
embedlog/src/el-perror.c \
embedlog/src/el-pmemory.c \
embedlog/src/el-print.c \
embedlog/src/el-puts.c \
embedlog/src/el-ts.c

It's in the apps/system/embedlog/Makefile

Objects appear in 'apps/system/embedlog/embedlog/src' directory and 'make clean'
removes them.

--
Best Regards
Michał Łyszczek
signature.asc

Matias N.

unread,
May 8, 2018, 11:50:30 AM5/8/18
to michal....@bofc.pl, nu...@googlegroups.com
I've looked into this app and you don't seem to be using Application.mk, which I want to use to have a minimal application Makefile and avoid reinventing the wheel. On a sidenote, I can't see the source files of this app, it vould seem they're missing from the repo.

Email had 1 attachment:

  • signature.asc
      1k (application/pgp-signature)

Matias N.

unread,
May 8, 2018, 11:58:29 AM5/8/18
to NuttX
I tried this and when recreating the Make.dep files (after I deleted .depend), I get:

make[3]: *** No rule to make target 'drive_controller.cxx', needed by '.depend'.  Stop

Could this be because in my case, the apps/external is a symlink to another directory? 

$ ls -l NuttX/apps/external
lrwxrwxrwx 1 v01d v01d 13 may  8 12:57 NuttX/apps/external -> ../../module

patacongo

unread,
May 8, 2018, 12:15:30 PM5/8/18
to NuttX

I tried this and when recreating the Make.dep files (after I deleted .depend), I get:

make[3]: *** No rule to make target 'drive_controller.cxx', needed by '.depend'.  Stop

Because you also have to provide the dependency path to the tool as you can see in most other Makefiles.

ROOTDEPPATH = --dep-path src
$(Q) $(MKDEP) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep

patacongo

unread,
May 8, 2018, 12:34:11 PM5/8/18
to NuttX
You can see the generic setup throughout the OS.  Look for example at nuttx/drivers/Makefile.  There is only one Makefile but each directory contains a Make.defs file.  The top level Makefile includes each sub-directory Make.defs:

DEPPATH = --dep-path .
ASRCS =
CSRCS =
VPATH = .
...
include analog$(DELIM)Make.defs
include audio$(DELIM)Make.defs
include bch$(DELIM)Make.defs
include can$(DELIM)Make.defs


Each Make.defs file includes the .c files with no subdirectory as in drivers/sensors/Make.defs:

ifeq ($(CONFIG_SENSORS_HCSR04),y)
  CSRCS += hc_sr04.c
endif


and sets up is own DEPPATH, VPATH, and include path as in drivers/sensors/Make.defs


DEPPATH += --dep-path sensors
VPATH += :sensors
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)sensors}


So each sub-directory is completely self contained, modularized,  and self described by the Make.defs file.  The single top-level Makefile simply needs to include the sub-directory's Make.defs file.

Reply all
Reply to author
Forward
0 new messages